package com.example.app12_data_storage.activity;

import android.app.ProgressDialog;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import androidx.activity.EdgeToEdge;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.example.app12_data_storage.R;

import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
import org.apache.hc.client5.http.impl.classic.BasicHttpClientResponseHandler;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.support.ClassicRequestBuilder;
import org.apache.hc.core5.http.message.BasicNameValuePair;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class NetworkActivity extends AppCompatActivity {

    private static final String TAG = "NetworkActivity";

    private EditText etNetworkUrl;
    private EditText etNetworkResult;

    RequestQueue queue;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_network);
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.ll_network), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return insets;
        });

        Log.i(TAG, "onCreate()");

        // 初始化视图控件
        etNetworkUrl = findViewById(R.id.et_network_url);
        etNetworkResult = findViewById(R.id.et_network_result);

        // 初始化请求队列
        queue = Volley.newRequestQueue(this);

    }

    /**
     * HttpUrlConnection发送Get请求
     *  1、显示ProcessDialog
     *  2、启动分线程，发送请求，得到响应数据
     *      ① 得到path
     *      ② 创建URL对象
     *      ③ 打开连接，得到HttpUrlConnection对象
     *      ④ 设置请求方式，设置连接超时时间，设置读取超时时间
     *      ⑤ 打开连接
     *      ⑥ 获取响应结果
     *      ⑦ 关闭连接
     *  3、在主线程显示响应结果，移除Dialog
     * @param view 发生点击事件的视图对象
     */
    public void httpUrlConnectionGet(View view) {
        // 显示Dialog
        final ProgressDialog dialog = ProgressDialog.show(this, null, "数据请求中...");
        // 启动分线程
        new Thread(() -> {
            // 得到请求路径
            String path = etNetworkUrl.getText().toString();
            if (TextUtils.isEmpty(path)) {
                runOnUiThread(() -> {
                    dialog.dismiss();
                    Toast.makeText(NetworkActivity.this, "请求URL不能为空~",
                            Toast.LENGTH_SHORT).show();
                });
            }
            // 拼接请求参数
            path = path + "?name=John&age=60";
            // 创建URL对象
            try {
                URL url = new URL(path);
                // 打开连接
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                // 设置请求方式
                connection.setRequestMethod("GET");
                // 设置请求时间
                connection.setConnectTimeout(5000);
                // 设置读取响应事件
                connection.setReadTimeout(5000);
                // 连接服务器
                connection.connect();
                // 获取响应码
                if (connection.getResponseCode() == 200) {
                    InputStream in = connection.getInputStream();
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    byte[] buffer = new byte[1024];
                    int len;
                    while((len = in.read(buffer)) != -1) {
                        out.write(buffer, 0, len);
                    }
                    final String result = out.toString();
                    // 关闭流
                    out.close();
                    in.close();
                    // 在主线程，显示响应结果，移除Dialog
                    runOnUiThread(() -> {
                        etNetworkResult.setText(result);
                        dialog.dismiss();
                    });
                }
                // 断开连接
                connection.disconnect();
            } catch (IOException e) {
                // 在主线程，显示响应结果，移除Dialog
                runOnUiThread(dialog::dismiss);
                Log.e(TAG, "httpUrlConnectionGet: " + e.getMessage(), e);
            }
        }).start();
    }

    /**
     * HttpUrlConnection发送Post请求
     * @param view 发生点击事件的视图对象
     */
    public void httpUrlConnectionPost(View view) {
        // 显示Dialog
        final ProgressDialog dialog = ProgressDialog.show(this, null, "数据请求中...");
        // 启动分线程
        new Thread(() -> {
            // 得到请求路径
            String path = etNetworkUrl.getText().toString();
            if (TextUtils.isEmpty(path)) {
                runOnUiThread(() -> {
                    dialog.dismiss();
                    Toast.makeText(NetworkActivity.this, "请求URL不能为空~",
                            Toast.LENGTH_SHORT).show();
                });
            }

            // 创建URL对象
            try {
                URL url = new URL(path);
                // 打开连接
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                // 设置请求方式
                connection.setRequestMethod("POST");
                // 设置请求时间
                connection.setConnectTimeout(5000);
                // 设置读取响应事件
                connection.setReadTimeout(5000);
                // 连接服务器
                connection.connect();
                // 得到输出流，发送请求参数
                OutputStream outputStream = connection.getOutputStream();
                outputStream.write("name=Eric&age=65".getBytes(StandardCharsets.UTF_8));

                // 获取响应码
                if (connection.getResponseCode() == 200) {
                    InputStream in = connection.getInputStream();
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    byte[] buffer = new byte[1024];
                    int len;
                    while((len = in.read(buffer)) != -1) {
                        out.write(buffer, 0, len);
                    }
                    final String result = out.toString();
                    // 关闭流
                    out.close();
                    in.close();
                    outputStream.close();
                    // 在主线程，显示响应结果，移除Dialog
                    runOnUiThread(() -> {
                        etNetworkResult.setText(result);
                        dialog.dismiss();
                    });
                }
                // 断开连接
                connection.disconnect();
            } catch (IOException e) {
                // 在主线程，显示响应结果，移除Dialog
                runOnUiThread(dialog::dismiss);
                Log.e(TAG, "httpUrlConnectionPost: " + e.getMessage(), e);
            }
        }).start();
    }

    /**
     * HttpClient发送Get请求
     * @param view 发生点击事件的视图对象
     */
    public void httpClientGet(View view) {
        // 显示Dialog
        final ProgressDialog dialog = ProgressDialog.show(this, null, "数据请求中...");
        // 启动分线程
        new Thread(() -> {
            // 得到请求路径
            String path = etNetworkUrl.getText().toString();
            if (TextUtils.isEmpty(path)) {
                runOnUiThread(() -> {
                    dialog.dismiss();
                    Toast.makeText(NetworkActivity.this, "请求URL不能为空~",
                            Toast.LENGTH_SHORT).show();
                });
            }
            // 拼接请求参数
            path = path + "?name=HttpClientGet&age=60";
            // 创建URL对象
            try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
                ClassicHttpRequest httpGet = ClassicRequestBuilder.get(path).build();
                String result = httpClient.execute(httpGet, response -> {
                    // 解析响应
                    if (response.getCode() == 200) {
                        HttpEntity httpEntity = response.getEntity();
                        return EntityUtils.toString(httpEntity);
                    }
                    return null;
                });
                // 在主线程，显示响应结果，移除Dialog
                runOnUiThread(() -> {
                    etNetworkResult.setText(result);
                    dialog.dismiss();
                });
            } catch (IOException e) {
                // 在主线程，显示响应结果，移除Dialog
                runOnUiThread(dialog::dismiss);
                Log.e(TAG, "httpClientGet: " + e.getMessage(), e);
            }
        }).start();
    }

    /**
     * HttpClient发送Post请求
     * @param view 发生点击事件的视图对象
     */
    public void httpClientPost(View view) {
        // 显示Dialog
        final ProgressDialog dialog = ProgressDialog.show(this, null, "数据请求中...");
        // 启动分线程
        new Thread(() -> {
            // 得到请求路径
            String path = etNetworkUrl.getText().toString();
            if (TextUtils.isEmpty(path)) {
                runOnUiThread(() -> {
                    dialog.dismiss();
                    Toast.makeText(NetworkActivity.this, "请求URL不能为空~",
                            Toast.LENGTH_SHORT).show();
                });
            }

            // 创建URL对象
            try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
                ClassicHttpRequest httpPost = ClassicRequestBuilder
                        // 设置请求方式和URL
                        .post(path)
                        // 设置请求参数
                        .setEntity(new UrlEncodedFormEntity(Arrays.asList(
                                new BasicNameValuePair("name", "HttpClientPost"),
                                new BasicNameValuePair("age", "5")
                        )))
                        .build();
                String result = httpClient.execute(httpPost, response -> {
                    // 解析响应
                    if (response.getCode() == 200) {
                        HttpEntity httpEntity = response.getEntity();
                        return EntityUtils.toString(httpEntity);
                    }
                    return null;
                });
                // 在主线程，显示响应结果，移除Dialog
                runOnUiThread(() -> {
                    etNetworkResult.setText(result);
                    dialog.dismiss();
                });
            } catch (IOException e) {
                // 在主线程，显示响应结果，移除Dialog
                runOnUiThread(dialog::dismiss);
                Log.e(TAG, "httpClientPost: " + e.getMessage(), e);
            }
        }).start();
    }

    /**
     * Volley发送Get请求
     * @param view 发生点击事件的视图对象
     */
    public void volleyGet(View view) {
        // 显示Dialog
        final ProgressDialog dialog = ProgressDialog.show(this, null, "数据请求中...");
        // 得到请求路径
        String path = etNetworkUrl.getText().toString();
        // 拼接请求参数
        path = path + "?name=VolleyGet&age=10";
        // 创建请求对象
        StringRequest request = new StringRequest(path, new Response.Listener<String>() {
            @Override
            public void onResponse(String res) {
                etNetworkResult.setText(res);
                dialog.dismiss();
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                Log.e(TAG, "onErrorResponse: " + volleyError.getMessage());
                dialog.dismiss();
            }
        });
        // 将请求对象添加到请求队列中
        queue.add(request);
    }

    /**
     * Volley发送Post请求
     * @param view 发生点击事件的视图对象
     */
    public void volleyPost(View view) {
        // 显示Dialog
        final ProgressDialog dialog = ProgressDialog.show(this, null, "数据请求中...");
        // 得到请求路径
        String path = etNetworkUrl.getText().toString();
        // 创建请求对象
        StringRequest request = new StringRequest(Request.Method.POST, path, new Response.Listener<String>() {
            @Override
            public void onResponse(String res) {
                etNetworkResult.setText(res);
                dialog.dismiss();
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                Log.e(TAG, "onErrorResponse: " + volleyError.getMessage());
                dialog.dismiss();
            }
        }) {
            /**
             * 重写此方法，设置请求参数
             * @return 请求参数
             * @throws AuthFailureError error
             */
            @Nullable
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String, String> params = new HashMap<>(10);
                params.put("name", "VolleyPost");
                params.put("age", "10");
                return params;
            }
        };

        // 将请求对象添加到请求队列中
        queue.add(request);
    }
}
